<?php
declare(strict_types=1);

namespace App\Controller;
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use App\Model\User;
use App\Libs\Wechat;
use App\Libs\Token;
use App\Libs\Cache;
use App\Libs\EasySms;
use Hyperf\Di\Annotation\Inject;
use Qbhy\HyperfAuth\AuthManager;
use function Hyperf\Config\config;

class LoginController extends AbstractController
{
    #[Inject]
    protected ValidatorFactoryInterface $validationFactory;
    #[Inject]
    protected AuthManager $auth;
    public function index() {
        $code = $this->request->input('code', false);
        $username = $this->request->input('username', false);
        $isRegister = $this->request->input('isRegister', false);
        if($isRegister) {
            $validator = $this->validationFactory->make(
                $this->request->all(),
                [
                    'username' => 'required',
                    'password' => 'required',
                    'code' => 'required',
                    'mobile' => 'required',
                    'email' => 'required',
                    'code' => 'required',
                    'code_key' => 'required',
                ],
                [
                    'required' => '参数必须填写',
                ]
            );
        }else{
            $validator = $this->validationFactory->make(
                $this->request->all(),
                [
                    'username' => 'required',
                    'password' => 'required',
                    'code' => 'required',
                    'code_key' => 'required',
                ],
                [
                    'required' => '参数必须填写',
                ]
            );
        }
        if ($validator->fails()){
            // Handle exception
            $errorMessage = $validator->errors()->first();
            return $this->error($errorMessage);
        }
        $bool = \Ella123\HyperfCaptcha\captcha_verify($this->request->input('code', ''), $this->request->input('code_key', ''));
        if(!$bool) return $this->error('图形验证码错误，请重新输入');
        
        //插入 用户表
        $user_info = User::where('username', $username)->first();
        //纷发token 和 用户信息
        if(!$user_info && $isRegister) {
            $user_info = new User();
            $ip = $this->request->getHeader('X-Forwarded-For');
            $user_info->ip = is_array($ip)?json_encode($ip):$ip;
            $user_info->mobile = $this->request->input('mobile');
            // $user_info->name = $this->request->input('name');
            $user_info->username = $this->request->input('username');
            $user_info->email = $this->request->input('email');
            $user_info->password = password_hash($this->request->input('password', ''), PASSWORD_DEFAULT);
            $user_info->save();
            $user_info = User::find($user_info->id);
        }else if(!$user_info) {
            return $this->error(message: '用户名错误');
        }else{
            // var_dump(password_hash($this->request->input('password', ''), PASSWORD_DEFAULT));
            if(!password_verify($this->request->input('password', ''), $user_info->password)) {
                return $this->error(message: '密码错误');
            }
        }

        $token = $this->auth->guard()->login($user_info);
        $data = [
            "accessToken" => $token,
            "refreshToken" => $token,
            "expires"=> date('m/d/Y H:i:s', time() + config('auth.guards.jwt.ttl')),
            "roleKey" => "custom",
            "permissions" => [
                "*:*:*"
            ]
        ];
        $data = array_merge($data, $user_info->toArray());
         
        return $this->success($data, $isRegister?'注册成功！':'登录成功！');
    }

    public function refreshToken(){
        try {  
            $token = $this->auth->guard()->refresh($this->request->input('refreshToken'));
            if(!$token) {
                return $this->error('刷新失败', 401);
            }
            
        } catch (\Exception $e) {
            return $this->error('刷新失败', 401);
        }
        $data = [
            "accessToken" => $token,
            "refreshToken" => $token,
            "expires"=> date('m/d/Y H:i:s', time() + config('auth.guards.jwt.ttl')),
            "roleKey" => "custom",
            "permissions" => [
                "*:*:*"
            ]
        ];
        $data = array_merge($data, $this->auth->guard()->user()->toArray());
         
        return $this->success($data, '刷新成功！');
    }

    public function miniLogin(){
        $code = $this->request->input('code', false);
        $login = $this->request->input('login', false);//session_key
        
        if(!$code && !$login) {
            return $this->error('参数不对，请重新打开页面');
        }
        $app = Wechat::app();
        //获取code
        $utils = $app->getUtils();
        //保存Token
        $accessToken = $app->getAccessToken();
        Cache::set('accessToken', $accessToken->getToken());
        //解密手机号
        if($login) {
            $session_key = $login;
            $detail = $this->request->input('detail', false);
            $token = $this->request->input('token', false);
            $user = Token::getUser($token);
            if(!$user) {
                return $this->error('参数不对，请重新启动小程序');
            }
            $decryptedData = $utils->decryptSession($session_key, $detail['iv'], $detail['encryptedData']);

            if ($decryptedData && isset($decryptedData['phoneNumber'])) {

                //先判断手机号是否已经存在
                $row = User::where('mobile', $decryptedData['phoneNumber'])->first();
                if($row) {
                    //存在手机号，则更新openid
                    $row->mini_openid = $user->mini_openid;
                    $row->save();
                    //删除之前的用户
                    $user->delete();
                    $user_info = $row;
                }else{
                    $user->mobile = $decryptedData['phoneNumber'];
                    $user->save();
                    $user_info = $user;
                }
            }else{
                return $this->error('非法请求，请联系管理员');
            }
        }else{
            
            try {
                $user = $utils->codeToSession($code);
                $session_key = $user['session_key'];
                var_dump($user);
            } catch (\Exception $e) {
                // var_export($e);
                return $this->error('请重新登录', 401);
            }
            //插入 用户表
            $user_info = User::where('mini_openid', $user['openid'])->first();

            $designer_id = $this->request->input('designer_id', 0);
            //如果是设计师，才增加分享id 获取设计师的agent_id
            $designer = User::select('group_id', 'agent_id')->where('id', $designer_id)->first();
            if(!$designer || $designer->group_id != 8) {
                $designer_id = 0;
            }

            //纷发toke 和 用户信息
            if(!$user_info) {
                $user_info = new User();
                $user_info->name = '微信用户';
                $user_info->mini_openid = $user['openid'];
                $user_info->group_id = 9;
                //如果设计师存在
                if($designer) {
                    $user_info->designer_id = $designer_id;
                    $user_info->agent_id = $designer->agent_id;
                }
                
                $user_info->mobile = substr($user['openid'], 0, 11);
                $user_info->status = 1;
                
            }else{
                //只有不存在推荐人的时候 才进行保存推荐人 ,并且设计师存在
                if($user_info->designer_id == 0 && $designer){
                    $user_info->designer_id = $designer_id;
                    $user_info->agent_id = $designer->agent_id;
                }
            }
            $user_info->save();
        }
        $token = Token::uuid($user_info->id);
        Token::setToken($token, $user_info);

        return $this->success(['user'=> $user_info, 'login'=> $session_key, 'access_token'=> $token, 'code'=> 1]);
    }

    public function sms(){
    	$mobile = $this->request->input('mobile', false);
        if(!$mobile) {
            return $this->error('参数不对，请重新打开页面');
        }
        //判断手机号是否已经发送
        if(Cache::get($mobile)) {
            return $this->error('短信已经发送，请稍后');
        }
        $code = rand(10000, 99999);

        //开发模式不发送短信
        if(config('app_env') == 'dev') {
            Cache::set($mobile, $code, 60);
            return $this->success(['code'=> 1, 'msg'=> '发送成功：' . $code]);
        }
        //发送短信
        $ret = (new EasySms())->send($mobile, $code);
        //判断发送
        if(isset($ret['aliyun']) && isset($ret['aliyun']['status']) && $ret['aliyun']['status'] == 'success') {
            Cache::set($mobile, $code, 60 * 5);
            return $this->success(['code'=> 1, 'msg'=> '发送成功']);
        }
        return $this->error('发送失败，清稍后再试');
    }
    /**
     * 获取验证码.
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws InvalidArgumentException
     */
    public function getCaptchaImage()
    {
        $data = \Ella123\HyperfCaptcha\captcha_create();
        return $this->success(['code' => $data['key'], 'img'=> $data['img']]);
    }
}